package com.zoe.onelink.util;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;

/**
 * <p>标题: </p>
 * <p>描述: </p>
 * <p>版权: Copyright (c) 2022</p>
 * <p>公司: 智业软件股份有限公司</p>
 *
 * @version: 1.0
 * @author: ruansheng
 * @date: 2022-05-25
 */
public class OnelinkContextHolder {

    /**
     * 这里不使用TransmittableThreadLocal,异步场景传递上下文统一使用 OnelinkContextTaskDecorator 进行处理
     * TransmittableThreadLocal在异步线程中上下文与父现场共用一个对象,如果父线程清理了上下文信息会导致异步线程中也丢失,需要单独处理
     */
    private static final ThreadLocal<Map<String, Object>> HOLDER = new ThreadLocal<>();


    public static Object getValue(String key) {
        Map<String, Object> holderMap = HOLDER.get();
        if (holderMap == null) {
            return null;
        }
        return holderMap.get(key);
    }

    public static Optional<Object> getOptional(String key) {
        Map<String, Object> holderMap = HOLDER.get();
        if (holderMap == null) {
            return Optional.empty();
        }
        return Optional.ofNullable(holderMap.get(key));
    }

    public static String getString(String key) {
        Object value = getValue(key);
        return value == null ? null : value.toString();
    }

    public static Integer getInteger(String key) {
        Object value = getValue(key);
        if (value == null) {
            return null;
        } else if (value instanceof Integer) {
            return (Integer) value;
        } else if (value instanceof String) {
            return Integer.valueOf(value.toString());
        }
        throw new NumberFormatException("Invalid integer value :" + value);
    }

    public static Boolean getBoolean(String key) {
        Object value = getValue(key);
        if (value == null) {
            return null;
        } else if (value instanceof Boolean) {
            return (Boolean) value;
        } else if (value instanceof String) {
            return Boolean.valueOf(value.toString());
        }
        throw new IllegalArgumentException("Invalid boolean value :" + value);
    }

    public static void putValue(Map<String, Object> paramMap) {
        if (paramMap == null || paramMap.isEmpty()) {
            return;
        }
        Map<String, Object> map = HOLDER.get();
        if (map == null) {
            // 创建一个新的map接受外部参数,避免数据在外部被修改
            HOLDER.set(new HashMap<>(paramMap));
        } else {
            map.putAll(paramMap);
        }
    }

    private static Object putValue(String key, Object value, boolean rewrite) {
        if (StrUtil.isBlank(key)) {
            return null;
        }
        Map<String, Object> holderMap = HOLDER.get();
        if (holderMap == null) {
            holderMap = new HashMap<>(1);
            HOLDER.set(holderMap);
        }
        return rewrite ? holderMap.put(key, value) : holderMap.putIfAbsent(key, value);
    }

    public static void putValue(String key, Object value) {
        putValue(key, value, true);
    }

    public static Object putIfAbsent(String key, String value) {
        return putValue(key, value, false);
    }

    public static void putIfNotNull(String key, Object value) {
        if (value == null) {
            return;
        }
        putValue(key, value);
    }

    public static void putIfNotBlank(String key, String value) {
        if (StrUtil.isBlank(value)) {
            return;
        }
        putValue(key, value);
    }

    public static Map<String, Object> getCopiedMap() {
        Map<String, Object> holderMap = HOLDER.get();
        return holderMap == null ? Collections.emptyMap() : new HashMap<>(holderMap);
    }

    public static Object remove(String key) {
        Map<String, Object> holderMap = HOLDER.get();
        if (holderMap == null) {
            return null;
        }
        return holderMap.remove(key);
    }

    public static void clear() {
        if (HOLDER.get() != null) {
            HOLDER.get().clear();
        }
    }

}
